package com.zenithmind.chat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.chat.mapper.ChatFriendMapper;
import com.zenithmind.chat.mapper.ChatFriendRequestMapper;
import com.zenithmind.chat.pojo.entity.ChatFriend;
import com.zenithmind.chat.pojo.entity.ChatFriendRequest;
import com.zenithmind.chat.pojo.vo.ChatFriendRequestVO;
import com.zenithmind.chat.service.ChatFriendRequestService;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.utils.BeanCopyUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 好友申请服务实现类
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChatFriendRequestServiceImpl extends ServiceImpl<ChatFriendRequestMapper, ChatFriendRequest> 
        implements ChatFriendRequestService {

    private final ChatFriendMapper friendMapper;

    @Override
    public PageResult<ChatFriendRequestVO> getFriendRequestPage(String userId, String type, Integer status, 
                                                               Integer pageNum, Integer pageSize) {
        Page<ChatFriendRequest> page = new Page<>(pageNum, pageSize);
        
        LambdaQueryWrapper<ChatFriendRequest> wrapper = new LambdaQueryWrapper<>();
        
        if ("sent".equals(type)) {
            wrapper.eq(ChatFriendRequest::getRequesterId, userId);
        } else if ("received".equals(type)) {
            wrapper.eq(ChatFriendRequest::getTargetId, userId);
        } else {
            wrapper.and(w -> w.eq(ChatFriendRequest::getRequesterId, userId)
                             .or()
                             .eq(ChatFriendRequest::getTargetId, userId));
        }
        
        wrapper.eq(status != null, ChatFriendRequest::getStatus, status)
               .orderByDesc(ChatFriendRequest::getRequestTime);
        
        IPage<ChatFriendRequest> result = page(page, wrapper);
        
        List<ChatFriendRequestVO> voList = result.getRecords().stream()
            .map(request -> convertToVO(request, userId))
            .collect(Collectors.toList());
        
        return PageResult.of(voList, result.getTotal());
    }

    @Override
    public List<ChatFriendRequestVO> getUserFriendRequests(String userId, String type, Integer status) {
        LambdaQueryWrapper<ChatFriendRequest> wrapper = new LambdaQueryWrapper<>();
        
        if ("sent".equals(type)) {
            wrapper.eq(ChatFriendRequest::getRequesterId, userId);
        } else if ("received".equals(type)) {
            wrapper.eq(ChatFriendRequest::getTargetId, userId);
        } else {
            wrapper.and(w -> w.eq(ChatFriendRequest::getRequesterId, userId)
                             .or()
                             .eq(ChatFriendRequest::getTargetId, userId));
        }
        
        wrapper.eq(status != null, ChatFriendRequest::getStatus, status)
               .orderByDesc(ChatFriendRequest::getRequestTime);
        
        List<ChatFriendRequest> requests = list(wrapper);
        
        return requests.stream()
            .map(request -> convertToVO(request, userId))
            .collect(Collectors.toList());
    }

    @Override
    public ChatFriendRequestVO getFriendRequestById(String id, String userId) {
        ChatFriendRequest request = getById(id);
        if (request == null) {
            throw new BusinessException("好友申请不存在");
        }
        
        // 检查权限
        if (!Objects.equals(request.getRequesterId(), userId) && 
            !Objects.equals(request.getTargetId(), userId)) {
            throw new BusinessException("无权限查看该申请");
        }
        
        return convertToVO(request, userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean handleFriendRequest(String requestId, Boolean accept, String responseMessage, String userId) {
        ChatFriendRequest request = getById(requestId);
        if (request == null) {
            throw new BusinessException("好友申请不存在");
        }
        
        if (!Objects.equals(request.getTargetId(), userId)) {
            throw new BusinessException("无权限处理该申请");
        }
        
        if (request.getStatus() != 0) {
            throw new BusinessException("该申请已被处理");
        }
        
        if (request.getExpireTime().isBefore(LocalDateTime.now())) {
            throw new BusinessException("该申请已过期");
        }
        
        // 更新申请状态
        request.setStatus(accept ? 1 : 2);
        request.setResponseMessage(responseMessage);
        request.setResponseTime(LocalDateTime.now());
        updateById(request);
        
        if (accept) {
            // 创建双向好友关系
            createFriendRelation(request.getRequesterId(), request.getTargetId(), 
                               request.getRequesterName(), UserContext.getUsername());
        }
        
        log.info("用户 {} {} 好友申请 {}", userId, accept ? "同意" : "拒绝", requestId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean withdrawFriendRequest(String requestId, String userId) {
        ChatFriendRequest request = getById(requestId);
        if (request == null) {
            throw new BusinessException("好友申请不存在");
        }
        
        if (!Objects.equals(request.getRequesterId(), userId)) {
            throw new BusinessException("无权限撤回该申请");
        }
        
        if (request.getStatus() != 0) {
            throw new BusinessException("该申请已被处理，无法撤回");
        }
        
        // 软删除申请
        removeById(requestId);
        
        log.info("用户 {} 撤回好友申请 {}", userId, requestId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteFriendRequest(String requestId, String userId) {
        ChatFriendRequest request = getById(requestId);
        if (request == null) {
            throw new BusinessException("好友申请不存在");
        }
        
        // 检查权限（申请人或目标用户都可以删除）
        if (!Objects.equals(request.getRequesterId(), userId) && 
            !Objects.equals(request.getTargetId(), userId)) {
            throw new BusinessException("无权限删除该申请");
        }
        
        removeById(requestId);
        
        log.info("用户 {} 删除好友申请 {}", userId, requestId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchHandleFriendRequests(List<String> requestIds, Boolean accept, String userId) {
        if (CollectionUtils.isEmpty(requestIds)) {
            return false;
        }
        
        for (String requestId : requestIds) {
            try {
                handleFriendRequest(requestId, accept, null, userId);
            } catch (Exception e) {
                log.error("批量处理好友申请失败: {}", requestId, e);
            }
        }
        
        return true;
    }

    @Override
    public Integer countFriendRequests(String userId, String type, Integer status) {
        LambdaQueryWrapper<ChatFriendRequest> wrapper = new LambdaQueryWrapper<>();
        
        if ("sent".equals(type)) {
            wrapper.eq(ChatFriendRequest::getRequesterId, userId);
        } else if ("received".equals(type)) {
            wrapper.eq(ChatFriendRequest::getTargetId, userId);
        } else {
            wrapper.and(w -> w.eq(ChatFriendRequest::getRequesterId, userId)
                             .or()
                             .eq(ChatFriendRequest::getTargetId, userId));
        }
        
        wrapper.eq(status != null, ChatFriendRequest::getStatus, status);
        
        return Math.toIntExact(count(wrapper));
    }

    @Override
    public Boolean checkRequestExists(String requesterId, String targetId) {
        LambdaQueryWrapper<ChatFriendRequest> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatFriendRequest::getRequesterId, requesterId)
               .eq(ChatFriendRequest::getTargetId, targetId)
               .eq(ChatFriendRequest::getStatus, 0); // 待处理
        
        return count(wrapper) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer cleanExpiredRequests(Integer days) {
        LocalDateTime expireTime = LocalDateTime.now().minusDays(days);
        
        LambdaQueryWrapper<ChatFriendRequest> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatFriendRequest::getStatus, 0)
               .lt(ChatFriendRequest::getExpireTime, expireTime);
        
        List<ChatFriendRequest> expiredRequests = list(wrapper);
        
        if (!CollectionUtils.isEmpty(expiredRequests)) {
            // 更新状态为过期
            expiredRequests.forEach(request -> request.setStatus(3));
            updateBatchById(expiredRequests);
        }
        
        return expiredRequests.size();
    }

    @Override
    public Object getRequestStatistics(String userId, String startTime, String endTime) {
        // 简化统计实现
        LambdaQueryWrapper<ChatFriendRequest> wrapper = new LambdaQueryWrapper<>();
        
        if (StringUtils.hasText(userId)) {
            wrapper.and(w -> w.eq(ChatFriendRequest::getRequesterId, userId)
                             .or()
                             .eq(ChatFriendRequest::getTargetId, userId));
        }
        
        long totalRequests = count(wrapper);
        
        return new Object() {
            public final Long total = totalRequests;
            public final Long pending = 0L;
            public final Long accepted = 0L;
            public final Long rejected = 0L;
        };
    }

    /**
     * 转换为VO对象
     */
    private ChatFriendRequestVO convertToVO(ChatFriendRequest request, String userId) {
        ChatFriendRequestVO vo = BeanCopyUtils.copyBean(request, ChatFriendRequestVO.class);
        
        // 设置状态文本
        switch (request.getStatus()) {
            case 0:
                vo.setStatusText("待处理");
                break;
            case 1:
                vo.setStatusText("已同意");
                break;
            case 2:
                vo.setStatusText("已拒绝");
                break;
            case 3:
                vo.setStatusText("已过期");
                break;
            default:
                vo.setStatusText("未知");
        }
        
        // 设置是否过期
        vo.setIsExpired(request.getExpireTime().isBefore(LocalDateTime.now()));
        
        // 设置是否可以处理（仅对接收方有效）
        vo.setCanHandle(Objects.equals(request.getTargetId(), userId) && 
                       request.getStatus() == 0 && 
                       !vo.getIsExpired());
        
        // 设置申请类型
        vo.setType(Objects.equals(request.getRequesterId(), userId) ? "sent" : "received");
        
        return vo;
    }

    /**
     * 创建好友关系
     */
    private void createFriendRelation(String userId1, String userId2, String userName1, String userName2) {
        LocalDateTime now = LocalDateTime.now();
        
        // 创建用户1 -> 用户2的关系
        ChatFriend friend1 = new ChatFriend();
        friend1.setUserId(userId1);
        friend1.setFriendId(userId2);
        friend1.setFriendName(userName2);
        friend1.setStatus(1);
        friend1.setGroupName("我的好友");
        friend1.setAddTime(now);
        friend1.setAddSource("好友申请");
        
        // 创建用户2 -> 用户1的关系
        ChatFriend friend2 = new ChatFriend();
        friend2.setUserId(userId2);
        friend2.setFriendId(userId1);
        friend2.setFriendName(userName1);
        friend2.setStatus(1);
        friend2.setGroupName("我的好友");
        friend2.setAddTime(now);
        friend2.setAddSource("好友申请");
        
        friendMapper.insert(friend1);
        friendMapper.insert(friend2);
    }
}
